/*
宏编程

Rust宏主要分为声明宏和过程宏两大类，其中过程宏又分为派生宏、属性宏和类函数宏，这个分类框架很清晰

在 Rust 中宏分为两大类：声明式宏( declarative macros ) macro_rules! 和三种过程宏( procedural macros ):
#[derive]，在之前多次见到的派生宏，可以为目标结构体或枚举派生指定的代码，例如 Debug 特征
类属性宏(Attribute-like macro)，用于为目标添加自定义的属性
类函数宏(Function-like macro)，看上去就像是函数调用
从根本上来说，宏是通过一种代码来生成另一种代码，如果大家熟悉元编程，就会发现两者的共同点。

macro_rules 宏定义
macro_export 宏导出


宏类型  	定义方式	                 主要特点	                                    典型应用
声明宏  	macro_rules!	            基于模式匹配的代码替换，使用相对简单	        vec!, println!
过程宏	    自定义函数操作 AST           操作 AST，更灵活强大	                        #[derive(Debug)]
├ 派生宏	#[proc_macro_derive]        为结构体或枚举自动实现 trait                    #[derive(Clone)]
├ 属性宏	#[proc_macro_attribute] 	为目标添加自定义属性并修改代码	                #[route(GET, "/")]
├ 类函数宏	#[proc_macro]	            像函数一样调用，操作标记序列	                sql!("SELECT *")


*/

use std::vec;

/// 可变参数
///
///在函数中 参数是固定的，而在宏函数中，参数的动态可变的
pub fn run1() {
    let name = "张三";
    println!("hello");
    println!("hello {}", name);
}
/// 宏展开
///
/// 由于宏会被展开成其它代码，且这个展开过程是发生在编译器对代码进行解释之前。
///
/// 因此，宏可以为指定的类型实现某个特征：先将宏展开成实现特征的代码后，再被编译。
///
/// 而函数就做不到这一点，因为它直到运行时才能被调用，而特征需要在编译期被实现。
///
pub fn run2() {
    vec![1, 2, 2, 2, 2];
}

///宏定义
///而现在，我们先来简单讲解下 ( $( $x:expr ),* ) 的含义。
///
///首先，我们使用圆括号 () 将整个宏模式包裹其中。紧随其后的是 $()，
///
///跟括号中模式相匹配的值(传入的 Rust 源代码)会被捕获，然后用于代码替换。
///
///在这里，模式 $x:expr 会匹配任何 Rust 表达式并给予该模式一个名称：$x。
///
///$() 之后的逗号说明 $() 所匹配的代码使用逗号分隔符分割，
///
///紧随逗号之后的 * 说明 * 之前的模式($()内的部分)会被匹配零次或任意多次(类似正则表达式)(且以逗号分割)。
///

macro_rules! vec {
        /*
        item ——一个项（item），像一个函数，结构体，模块等。
        block ——一个块 （block）（即一个语句块或一个表达式，由花括号所包围）
        stmt —— 一个语句（statement）
        pat ——一个模式（pattern）
        expr —— 一个表达式（expression）
        ty ——一个类型（type）
        ident—— 一个标识符（indentfier）
        path —— 一个路径（path）（例如，foo，::std::mem::replace，transmute::<_, int>，...）
        meta —— 一个元数据项；位于#[...]和#![...]属性
        tt——一个词法树
        vis——一个可能为空的Visibility限定词 
        */
    ($( $x:expr),*) => {
        let mut temp_vec=Vec::new();
        $(temp_vec.push($x);)*
        temp_vec;
    };
}

macro_rules! add {
    //表达式1
    ($a:expr,$b:expr) => {{
        $a + $b;
    }};
    //表达式2
    ($a:expr) => {
        $a * $a;
    };
}

macro_rules! add_as {
    ($a:expr,$b:ty) => {
        $a as $b;
    };
    
}


///调用定义的 宏 vec
pub fn run3() {
    vec![1, 2, 3, 4];
    vec![4, 3, 2, 1];
    vec![5, 6, 7, 8];

    add!(1, 2);
    add!(5);
    add_as!(2,i32);
}

pub fn run4() {}

pub fn run() {
    run1();
}
